package terra.managers;

import java.util.ArrayList;

import terra.Config;
import terra.definitions.CraftDef;
import terra.definitions.CraftDef.Ingridient;
import terra.definitions.CraftDef.Result;
import terra.model.CraftItem;
import terra.model.object.Player;
import terra.model.object.item.Item;
import terra.network.packet.client.RequestCraftItem;
import terra.network.packet.server.CraftResult;
import terra.util.MathUtil;

public class CraftManager {

	/*
	 * Каждый рецепт имеет свой идентификатор. У каждого рецепта есть
	 * идентификатор создаваемого предмета, минимальное и максимальное
	 * количество создаваемых предметов идентификатор главного ингридиента
	 * список всех ингридиентов (идентификатор и количество)
	 * 
	 * 
	 * При попытке создания сначала проверяем на главный ингридиент, потом уже
	 * все остальные
	 */
	static CraftManager instance;

	/**
	 * Метод создания предметов
	 * */
	public ArrayList<CraftItem> tryCraft(ArrayList<CraftItem> ingridients,
			Player player, boolean all) {
		System.out.println("Try to craft.");
		if (player.inv.getItems().size() >=player.inv.getMaxCount())
			return ingridients;
		ArrayList<CraftDef> defList = new ArrayList<CraftDef>();
		for (CraftDef d : DefManager.crafts.values())
			for (CraftItem ingridient : ingridients)
				if (ingridient.itemId == d.mainIngridient
						&& ingridients.size() == d.ingridients.size())
					defList.add(d);

		if (defList.size() == 0) {
			System.out.println("defList.size() == 0)");
			return ingridients;
		}
		int countObject = ingridients.size();
		CraftDef used = null;
		for (CraftDef recipe : defList) {
			int cnt = 0;
			for (Ingridient recIngridient : recipe.ingridients) {
				for (CraftItem ingridient : ingridients) {
					if (ingridient == null)
						continue;
					// System.out.println("try to compare : " +
					// recIngridient.itemId + "  and  " + ingridient.itemId);
					if (recIngridient.itemId == ingridient.itemId)
						cnt++;
				}
				// System.out.println("compare count : " + cnt + "  and  " +
				// countObject);

				if (cnt == countObject)
					used = recipe;
			}
		}
		if (used == null)
			return ingridients;

		// if (used != null)
		// System.out.println("Recipe for " + used.name);

		boolean canCraft = true;
		for (Ingridient ing : used.ingridients) {
			for (CraftItem obj : ingridients) {
				if (ing.itemId == obj.itemId)
					if (ing.count > obj.count)
						canCraft = false;
			}
		}

		// для крафта сразу максимального количества предметов, на которые есть
		// ингридиенты в окне создания.
		// максимальное количество созданных предметов берется исходя из
		// наименьшего количества инргидиентов в наличии / на количество нужных
		// для крафта
		int cnt = -1;
		if (all)
			for (Ingridient ing : used.ingridients)
				for (CraftItem obj : ingridients) {
					if (obj == null)
						continue;
					if (ing.itemId == obj.itemId) {
						int c = obj.count / ing.count;
						if (cnt == -1)
							cnt = c;
						else if (c < cnt)
							cnt = c;
					}
				}
		// проверяем реальное наличие предметов у персонажа в инвентаре
		for (Ingridient obj : used.ingridients) {
			Item item = player.inv.getItemByItemId(obj.itemId);
			if ((!all && item.getCount() < obj.count)
					|| (all && item.getCount() < obj.count * cnt)) {
				canCraft = false;
				break;
			}
		}

		// System.out.println("Have all ingridients?  " + canCraft);
		if (!canCraft)
			return ingridients;
		for (Ingridient obj : used.ingridients) {
			Item item = player.inv.getItemByItemId(obj.itemId);
			item.setCount(item.getCount() - (all ? obj.count * cnt : obj.count));
			for (CraftItem ingridient : ingridients)
				if (ingridient != null && ingridient.itemId == obj.itemId)
					ingridient.count -= (all ? obj.count * cnt : obj.count);
			if (item.getCount() == 0)
				player.inv.removeItem(item);
		}
		Result result = null;
		// TODO if all ывыбирать результат столько раз, на сколько хватает
		// ресурсов, или на каждый раз выбирать результат и выдавать итем?!
		if (all) {

		} else

		if (used.results.size() > 1) {
			int chance = MathUtil.rnd.nextInt(Config.MAX_CHANCE);

			// TODO выбрать результат исходя из шанса

		} else
			result = used.results.get(0);
		int count = result.minCount;
		if (result.minCount != result.maxCount)
			count = result.minCount
					+ (MathUtil.rnd.nextInt(result.maxCount - result.minCount));
		if (all)
			count *= cnt;
		if (player.inv.getItemByItemId(result.itemId) != null
				&& player.inv.getItemByItemId(result.itemId).getDef().isStackable)
			player.inv.changeCount(result.itemId, count);
		// player.inv.getItemByItemId(result.itemId).addCount(count);
		else
			player.inv.pickupItem(result.itemId, count);
		System.out.println("PLAYER with ID " + player.getObjectId()
				+ " crafted " + DefManager.allItems.get(result.itemId).name);
		// LOG.info("PLAYER with ID "+ player.getObjectId() + " crafted " +
		// ItemManager.all.get(result.itemId).name);
		if (!player.knownRecipes.contains(used.recipeId))
			player.knownRecipes.add(used.recipeId);

		CraftResult craftResult = new CraftResult(player.getObjectId());
		craftResult.craftResult = CraftResult.SUCCESS;
		for (int i = 0; i < RequestCraftItem.COUNT; i++) {
			if (i < ingridients.size()) {
				if (ingridients.get(i) == null) {
					craftResult.itemOids[i] = -1;
					craftResult.itemIds[i] = -1;
					craftResult.itemCounts[i] = -1;
				} else {
					craftResult.itemOids[i] = ingridients.get(i).objectId;
					craftResult.itemIds[i] = ingridients.get(i).itemId;
					craftResult.itemCounts[i] = ingridients.get(i).count;
				}
			} else {
				craftResult.itemOids[i] = -1;
				craftResult.itemIds[i] = -1;
				craftResult.itemCounts[i] = -1;
			}
		}
		player.send(craftResult);
		return ingridients;
	}

	public static CraftManager getInstance() {
		if (instance == null)
			return instance = new CraftManager();
		return instance;
	}

}
